package cc.eddic.pratice.programmingparadigms.streampractice.impl;

import cc.eddic.pratice.programmingparadigms.exam.domain.Answer;
import cc.eddic.pratice.programmingparadigms.exam.domain.Option;
import cc.eddic.pratice.programmingparadigms.exam.domain.Question;
import cc.eddic.pratice.programmingparadigms.streampractice.QuestionAccuracy;
import cc.eddic.pratice.programmingparadigms.streampractice.QuestionAndAnswer;
import cc.eddic.pratice.programmingparadigms.streampractice.ScoreOfStudentAndCategory;
import cc.eddic.pratice.programmingparadigms.streampractice.StreamPractice;

import java.util.*;
import java.util.stream.Collectors;

public class StreamPracticeTyqImpl implements StreamPractice {
    @Override
    public List<QuestionAndAnswer> mapToQuestionAndAnswer(List<Question> questionList) {
        return questionList.stream()
                //把Question转成QuestionAndAnswer
                .map(question -> new QuestionAndAnswer(question.getNo(),
                        question.getDescription(),
                        question.getOptions().stream()
                                .filter(Option::isCorrectAnswer)
                                .findFirst()
                                .orElse(new Option(" ", '*', true))
                                .getChoice(),
                        question.getOptions().stream()
                                .filter(Option::isCorrectAnswer)
                                .findFirst()
                                .orElse(new Option(" ", '*', true))
                                .getAnswer()))
                .collect(Collectors.toList());
    }

    //    Stream实现QuestionAccuracy
    @Override
    public List<QuestionAccuracy> calculateAccuracy(List<Answer> answerList) {
        //计算参加考试总人数
        Set<String> studentCount = new HashSet<>();
        for (Answer answer : answerList) {
            studentCount.add(answer.getStudent().getName());
        }
        int num = studentCount.size();
        //返回QA对象
        return answerList.stream()
                .collect(Collectors.groupingBy(answer -> answer.getQuestion().getNo()))
                .entrySet().stream()
                .map(entry -> new QuestionAccuracy(entry.getKey(), " ",
                        entry.getValue().stream()
                                .filter(answer -> answer.getChoice() == answer.getQuestion().getOptions().stream().filter(Option::isCorrectAnswer).findFirst().orElseThrow(() -> new IllegalArgumentException(" ")).getChoice())
                                .count() * 1.0 / num
                )).collect(Collectors.toList());
    }

    @Override
    public List<ScoreOfStudentAndCategory> calculateScoreOfStudentAndSubCategory(List<Answer> answerList) {
        Map<String, List<Answer>> answerGroupByName = answerList.stream()
                .collect(Collectors.groupingBy(answer -> answer.getStudent().getName()));
        List<ScoreOfStudentAndCategory> scoreOfStudentAndCategories = new ArrayList<>();
        for (String name : answerGroupByName.keySet()) {
            List<ScoreOfStudentAndCategory> list = answerGroupByName.get(name).stream()
                    .collect(Collectors.groupingBy(answer -> answer.getQuestion().getSubCategory().getName()))
                    .entrySet().stream()
                    .map(entrySet -> new ScoreOfStudentAndCategory(name, entrySet.getKey(), (int) entrySet.getValue().stream()
                            .filter(answer -> answer.getChoice() == answer.getQuestion().getOptions().stream().filter(Option::isCorrectAnswer).findFirst().orElseThrow(() -> new IllegalArgumentException("找不到正确答案")).getChoice()).count() * 4))
                    .collect(Collectors.toList()).stream()
                    .filter(scoreOfStudentAndCategory -> scoreOfStudentAndCategory.getScore() > 0)
                    .collect(Collectors.toList());
            scoreOfStudentAndCategories.addAll(list);
        }
        return scoreOfStudentAndCategories;
    }
}